package com.boot.unity.api.wx.utils;

import com.alibaba.fastjson.JSON;
import com.boot.unity.api.wx.dto.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author XH.M
 * @create 2020-09-25 15:01
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PayUtil {
    private final RestTemplate restTemplate;
    private final ApplicationEventPublisher publisher;

    /**
     * 订单查询  订单支付状态查询   统计一下支付成功，回调失败的订单
     *SHFW00004
     *traceID   交易流水
     *commID    商户号
     */

    public ResponseBean invokeSHFW00004(String commID, Map body, String reqTime, TraceRecordDTO traceRecordDTO){
        String serviceCode = ServiceCodeEnum.SHFW00004.getServiceCode();
        String switch_json = buildParams(serviceCode, commID, body, reqTime);
        String response_json = post(switch_json);

        publishTraceRecord(traceRecordDTO, serviceCode, commID, reqTime, switch_json, response_json);
        return JSON.parseObject(response_json,ResponseBean.class);
    }

    /**
     * 获取被扫支付地址URL
     *
     * @param commID  商户标识
     * @param body    请求报文体
     * @param reqTime 请求时间
     * @return
     */
    public ResponseBean invokeSHFW00002(String commID, Map body, String reqTime, TraceRecordDTO traceRecordDTO) {
        String serviceCode = ServiceCodeEnum.SHFW00002.getServiceCode();
        String switch_json = buildParams(serviceCode, commID, body, reqTime);
        String response_json = post(switch_json);
        publishTraceRecord(traceRecordDTO, serviceCode, commID, reqTime, switch_json, response_json);
        return JSON.parseObject(response_json,ResponseBean.class);
    }

    /**
     * 交易退款
     * @param commID
     * @param body
     * @param reqTime
     * @return
     */
    public ResponseBean invokeSHFW00005(String commID, Map body, String reqTime, TraceRecordDTO traceRecordDTO) {
        String serviceCode = ServiceCodeEnum.SHFW00005.getServiceCode();
        String switch_json = buildParams(serviceCode, commID, body, reqTime);
        String response_json = post(switch_json);
        publishTraceRecord(traceRecordDTO, serviceCode, commID, reqTime, switch_json, response_json);
        return JSON.parseObject(response_json,ResponseBean.class);
    }

    /**
     * 对账单下载
     * @param commID
     * @param body
     * @param reqTime
     * @param traceRecordDTO
     * @return
     */
    public ResponseBean invokeSHFW00008(String commID, Map body, String reqTime, TraceRecordDTO traceRecordDTO){
        String serviceCode = ServiceCodeEnum.SHFW00008.getServiceCode();
        String switch_json = buildParams(serviceCode, commID, body, reqTime);
        String response_json = post(switch_json);
        publishTraceRecord(traceRecordDTO, serviceCode, commID, reqTime, switch_json, response_json);
        return JSON.parseObject(response_json,ResponseBean.class);
    }

    /**
     * 微信小程序预下单
     *
     * @param commID
     * @param body
     * @param reqTime
     * @return
     */
    public ResponseBean invokeSHFW00009(String commID, Map body, String reqTime, TraceRecordDTO traceRecordDTO) {
        String serviceCode = ServiceCodeEnum.SHFW00009.getServiceCode();
        String switch_json = buildParams(serviceCode, commID, body, reqTime);
        String response_json = post(switch_json);
        publishTraceRecord(traceRecordDTO, serviceCode, commID, reqTime, switch_json, response_json);
        return JSON.parseObject(response_json,ResponseBean.class);
    }

    /**
     * 监管账户到结算账户的转账交易
     * @param commID
     * @param body
     * @param reqTime
     * @return
     */
    public ResponseBean invokeSHFW00013(String commID, Map body, String reqTime, TraceRecordDTO traceRecordDTO) {
        String serviceCode = ServiceCodeEnum.SHFW00013.getServiceCode();
        String switch_json = buildParams(serviceCode, commID, body, reqTime);
        String response_json = post(switch_json);
        publishTraceRecord(traceRecordDTO, serviceCode, commID, reqTime, switch_json, response_json);
        return JSON.parseObject(response_json,ResponseBean.class);
    }


    /**
     * 构建json参数
     */
    private String buildParams(String serviceCode, String commID, Map body, String reqTime) {
        Map<String, String> action = new HashMap<>();
        action.put("serviceCode", serviceCode);          // 服务名
        action.put("traceID", reqTime + commID);         // 交易流水标识
        action.put("commID", commID);                    // 商户标识
        action.put("reqTime", reqTime);                  // 请求发送时间yyyyMMddHHmmss
        action.put("version", "1.0");     // 协议版本
        Map<String, String> allParams = new HashMap();
        allParams.putAll(action);
        allParams.putAll(body);
        try {
            String sign = sign(allParams);
            action.put("sign", sign);
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException("参数异常!");
        }
        RequestBean requestBean = new RequestBean(action, body);
        String switch_json = JSON.toJSONString(requestBean);
        return switch_json;
    }

    /**
     * 获取签名
     */
    private String sign(Map<String, String> params) throws UnsupportedEncodingException {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);
        StringBuilder sb = new StringBuilder(512);
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            value = URLEncoder.encode(value, "UTF-8");
            sb.append(key).append("=").append(value).append("&");
        }
        String signTemp = sb.append("key=").append("uIJI12upxv499Juil33").toString();
        String sign = DigestUtils.sha256Hex(signTemp).toLowerCase();
        if (log.isDebugEnabled()){
            log.debug("signTemp::{}", signTemp);
            log.debug("sign::{}", sign);
        }
        return sign;
    }

    /** 发起请求*/
    private String post(String switch_json){
        log.error("发起请求：{}",switch_json);
        try {
            //restTemplate.getRequestFactory().wait(15000);//请求发送后，等15秒
            ResponseEntity<String> entity = restTemplate.postForEntity("https://weihaizhsq.sdrcu.com/bsp/dataService?switch_json={0}", null, String.class, switch_json);
            log.error("请求entity:{}",JSON.toJSONString(entity));
            if (entity.getStatusCode().is2xxSuccessful()) {
                String text = entity.getBody();
                return text;
                //return JSON.parseObject(text,ResponseBean.class);
            }else {
                // 写入数据库记录，方便错误排查
                log.error("switch:[{}]请求失败",switch_json);
            }
        }catch (Exception e){
            // 写入数据库记录，方便异常排查
            e.printStackTrace();
            log.error("switch:[{}]请求异常", switch_json);
            log.error("switch:请求异常信息:{}",e.getMessage());
        }
        return null;
    }

    private void publishTraceRecord(TraceRecordDTO traceRecordDTO, String serviceCode, String commID, String reqTime, String switchJson, String responseJson){
        TrainBankTraceRecord traceRecord = new TrainBankTraceRecord();
        BeanUtils.copyProperties(traceRecordDTO, traceRecord);
        traceRecord.setServiceCode(serviceCode);
        traceRecord.setTraceId(reqTime+commID);
        traceRecord.setCommId(commID);
        traceRecord.setReqTime(reqTime);
        traceRecord.setVersion("1.0");
        traceRecord.setSwitchJson(switchJson);
        traceRecord.setResponseJson(responseJson);
        publisher.publishEvent(traceRecord);
    }


    /**
     * 账单号在redis中key前缀
     */
    private static final String PAY_ORDER_ID_PREFIX = "pay:orderId:";
}
